#!/bin/bash

# bond mode=4 (802.3ad LACP) 配置和优化脚本

echo "bond mode=4 (802.3ad LACP) 配置和优化工具"
echo "=========================================="

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 显示bond mode=4诊断信息
show_bond_diagnostics() {
    echo -e "${BLUE}=== bond mode=4 诊断信息 ===${NC}"
    
    # 检查bonding模块
    if lsmod | grep -q bonding; then
        echo -e "${GREEN}✓ bonding模块已加载${NC}"
    else
        echo -e "${RED}✗ bonding模块未加载${NC}"
        echo "请运行: modprobe bonding"
    fi
    
    # 检查bond接口
    if [ -d "/proc/net/bonding" ]; then
        echo -e "${GREEN}✓ bond接口目录存在${NC}"
        
        for bond in /proc/net/bonding/*; do
            if [ -f "$bond" ]; then
                bond_name=$(basename "$bond")
                echo -e "\n${YELLOW}--- $bond_name 状态 ---${NC}"
                
                # 显示bond模式
                mode=$(grep "Bonding Mode" "$bond" 2>/dev/null | cut -d: -f2 | tr -d ' ')
                echo "模式: $mode"
                
                if [[ "$mode" == *"802.3ad"* ]]; then
                    echo -e "${GREEN}✓ 使用802.3ad LACP模式${NC}"
                else
                    echo -e "${YELLOW}⚠ 当前不是802.3ad模式${NC}"
                fi
                
                # 显示从属接口状态
                echo "从属接口状态:"
                grep -A 5 "Slave Interface" "$bond" 2>/dev/null | while read line; do
                    if [[ $line =~ "Slave Interface" ]]; then
                        interface=$(echo $line | cut -d: -f2 | tr -d ' ')
                        echo "  - $interface"
                    elif [[ $line =~ "MII Status" ]]; then
                        status=$(echo $line | cut -d: -f2 | tr -d ' ')
                        if [[ "$status" == "up" ]]; then
                            echo -e "    ${GREEN}状态: $status${NC}"
                        else
                            echo -e "    ${RED}状态: $status${NC}"
                        fi
                    fi
                done
                
                # 显示LACP信息
                echo "LACP信息:"
                grep -E "(LACP rate|Aggregator ID|Partner Mac|Partner Key)" "$bond" 2>/dev/null | while read line; do
                    echo "  $line"
                done
                
                # 显示传输哈希策略
                hash_policy=$(grep "Transmit Hash Policy" "$bond" 2>/dev/null | cut -d: -f2 | tr -d ' ')
                if [ ! -z "$hash_policy" ]; then
                    echo "传输哈希策略: $hash_policy"
                    if [[ "$hash_policy" == *"layer3+4"* ]]; then
                        echo -e "  ${GREEN}✓ 使用layer3+4哈希策略（推荐）${NC}"
                    else
                        echo -e "  ${YELLOW}⚠ 建议使用layer3+4哈希策略${NC}"
                    fi
                fi
            fi
        done
    else
        echo -e "${RED}✗ 未发现bond接口${NC}"
    fi
    
    echo ""
}

# 显示网络接口流量统计
show_interface_traffic() {
    echo -e "${BLUE}=== 网络接口流量统计 ===${NC}"
    
    # 获取当前流量统计
    cat /proc/net/dev | grep -E "(eth|bond|ens)" | while read line; do
        interface=$(echo $line | cut -d: -f1 | tr -d ' ')
        rx_bytes=$(echo $line | awk '{print $2}')
        tx_bytes=$(echo $line | awk '{print $10}')
        rx_packets=$(echo $line | awk '{print $3}')
        tx_packets=$(echo $line | awk '{print $11}')
        
        # 转换为MB
        rx_mb=$((rx_bytes / 1024 / 1024))
        tx_mb=$((tx_bytes / 1024 / 1024))
        
        echo "$interface: RX ${rx_mb}MB (${rx_packets}包) TX ${tx_mb}MB (${tx_packets}包)"
    done
    
    echo ""
}

# 检查交换机LACP配置建议
check_switch_config() {
    echo -e "${BLUE}=== 交换机LACP配置检查 ===${NC}"
    
    echo "请检查以下交换机配置:"
    echo "1. LACP协议是否启用"
    echo "2. 端口是否配置为LACP模式"
    echo "3. 聚合组配置是否正确"
    echo "4. LACP协商状态是否正常"
    
    echo ""
    echo "常见交换机配置命令:"
    echo "Cisco:"
    echo "  interface range gi0/1-2"
    echo "  channel-group 1 mode active"
    echo "  interface port-channel 1"
    echo "  switchport mode trunk"
    
    echo ""
    echo "Huawei:"
    echo "  interface eth-trunk 1"
    echo "  mode lacp-static"
    echo "  interface gigabitethernet 0/0/1"
    echo "  eth-trunk 1"
    
    echo ""
}

# 优化bond配置
optimize_bond_config() {
    echo -e "${BLUE}=== bond配置优化建议 ===${NC}"
    
    echo "推荐的bond mode=4配置:"
    echo ""
    echo "1. 基本配置:"
    echo "   BONDING_OPTS=\"mode=4 miimon=100\""
    echo ""
    echo "2. 优化配置（推荐）:"
    echo "   BONDING_OPTS=\"mode=4 miimon=100 xmit_hash_policy=layer3+4\""
    echo ""
    echo "3. 高级配置:"
    echo "   BONDING_OPTS=\"mode=4 miimon=100 xmit_hash_policy=layer3+4 lacp_rate=fast\""
    echo ""
    echo "参数说明:"
    echo "  - mode=4: 使用802.3ad LACP模式"
    echo "  - miimon=100: 每100ms检查链路状态"
    echo "  - xmit_hash_policy=layer3+4: 基于IP和端口哈希（推荐）"
    echo "  - lacp_rate=fast: 快速LACP协商"
    echo ""
    
    echo "应用配置:"
    echo "1. 编辑bond配置文件:"
    echo "   vi /etc/sysconfig/network-scripts/ifcfg-bond0"
    echo ""
    echo "2. 重启网络服务:"
    echo "   systemctl restart network"
    echo ""
    echo "3. 验证配置:"
    echo "   cat /proc/net/bonding/bond0"
    echo ""
}

# 测试bond负载均衡
test_bond_load_balancing() {
    echo -e "${BLUE}=== bond负载均衡测试 ===${NC}"
    
    echo "测试方法:"
    echo "1. 启动优化版服务器:"
    echo "   ./bond_mode4_optimization -p 8888 -i bond0"
    echo ""
    echo "2. 使用多IP客户端测试:"
    echo "   ./tcp_client_bond -s <服务器IP> -d 1000 -n 16 -m"
    echo ""
    echo "3. 监控网络流量:"
    echo "   watch -n 1 'cat /proc/net/dev | grep -E \"(eth|bond)\"'"
    echo ""
    echo "4. 检查bond状态:"
    echo "   watch -n 1 'cat /proc/net/bonding/bond0 | grep -E \"(Slave Interface|MII Status)\"'"
    echo ""
    
    echo "预期结果:"
    echo "- 多个从属接口都应该显示 'MII Status: up'"
    echo "- 网络流量应该分布到多个接口"
    echo "- 聚合带宽应该接近各接口带宽之和"
    echo ""
}

# 故障排除
troubleshooting() {
    echo -e "${BLUE}=== 故障排除指南 ===${NC}"
    
    echo "常见问题及解决方案:"
    echo ""
    echo "1. 只有一个网卡工作:"
    echo "   - 检查交换机LACP配置"
    echo "   - 验证LACP协商状态"
    echo "   - 尝试使用 xmit_hash_policy=layer3+4"
    echo ""
    echo "2. LACP协商失败:"
    echo "   - 检查网线连接"
    echo "   - 验证交换机端口配置"
    echo "   - 检查LACP版本兼容性"
    echo ""
    echo "3. 负载不均衡:"
    echo "   - 使用多IP绑定客户端"
    echo "   - 增加并发连接数"
    echo "   - 调整哈希策略"
    echo ""
    echo "4. 性能不达预期:"
    echo "   - 检查CPU使用率"
    echo "   - 验证内存带宽"
    echo "   - 监控网络延迟"
    echo ""
    
    echo "调试命令:"
    echo "  # 查看bond状态"
    echo "  cat /proc/net/bonding/bond0"
    echo ""
    echo "  # 查看网络统计"
    echo "  cat /proc/net/dev"
    echo ""
    echo "  # 查看LACP统计"
    echo "  cat /proc/net/bonding/bond0 | grep -i lacp"
    echo ""
    echo "  # 实时监控"
    echo "  watch -n 1 'cat /proc/net/bonding/bond0 | grep -E \"(Slave Interface|MII Status)\"'"
    echo ""
}

# 主菜单
show_menu() {
    echo -e "${GREEN}请选择操作:${NC}"
    echo "1. 显示bond诊断信息"
    echo "2. 显示网络接口流量"
    echo "3. 检查交换机配置建议"
    echo "4. 优化bond配置"
    echo "5. 测试bond负载均衡"
    echo "6. 故障排除指南"
    echo "7. 运行完整诊断"
    echo "8. 退出"
    echo ""
}

# 运行完整诊断
run_full_diagnostics() {
    echo -e "${BLUE}=== 运行完整诊断 ===${NC}"
    show_bond_diagnostics
    show_interface_traffic
    check_switch_config
    optimize_bond_config
    test_bond_load_balancing
    troubleshooting
}

# 主程序
main() {
    while true; do
        show_menu
        read -p "请输入选择 (1-8): " choice
        
        case $choice in
            1)
                show_bond_diagnostics
                ;;
            2)
                show_interface_traffic
                ;;
            3)
                check_switch_config
                ;;
            4)
                optimize_bond_config
                ;;
            5)
                test_bond_load_balancing
                ;;
            6)
                troubleshooting
                ;;
            7)
                run_full_diagnostics
                ;;
            8)
                echo "退出程序"
                exit 0
                ;;
            *)
                echo -e "${RED}无效选择，请重新输入${NC}"
                ;;
        esac
        
        echo ""
        read -p "按回车键继续..."
        clear
    done
}

# 检查是否以root权限运行
if [ "$EUID" -ne 0 ]; then
    echo -e "${YELLOW}警告: 建议以root权限运行此脚本以获得完整功能${NC}"
    echo ""
fi

# 运行主程序
main
